#pragma once
#include <string>

/**
 * Klasa zasobu.
 *
 * @author Krzysztof Klein
 * @version 0.1
 */
class Resource
{
	friend class ResourceManager;

public:

	/**
	 * Typ zasobu
	 */
	enum Type
	{
		//! Siatka
		MeshResource,

		//! Tekstura
		TextureResource,

		//! Efekt (Fx-Tekstura)
		FxTextureResource,

		//! Obraz
		ImageResource,

		//! Dzwiek
		SoundResource,

		//! Poziom
		LevelResource,

		//! Zapisana gra
		SavedGameResource,

		//! Dane binarne
		RawDataResource
	};

protected:

	/**
	 * Nazwa zasobu
	 */
	std::string name;

private:

	/**
	 * Liczba referencji do zasobu
	 */
	unsigned refCount;

	/**
	 * Bufor danych zasobu
	 */
	void* data;

	/**
	 * Rozmiar bufora danych zasobu
	 */
	unsigned dataSize;


	/**
	 * Dane pliku
	 */
	void* hFile; // uchwyt pliku
	void* hMapping; // uchwyt mapowania pliku

	/**
	 * Laduje dane zasobu z pliku.
	 * Nie zmienia nazwy zasobu.
	 */
	bool openFile(const std::string &fileName);

	/**
	 * Zamyka plik zasobu.
	 */
	void closeFile();

	/**
	 * Laduje zasob.
	 */
	virtual bool load() = 0;

	/**
	 * ...
	 */
	virtual void unload() { }

protected:

	/**
	 * Konstruktor domyslny
	 */
	Resource() : refCount(0), data(NULL), dataSize(0), hFile(NULL), hMapping(NULL) { }

	/**
	 * Destruktor
	 */
	virtual ~Resource();

public:

	/**
	 * Zwieksza liczbe referencji
	 */
	void addRef() { refCount++; }

	/**
	 * Zmniejsza liczbe referencji.
	 * Jezeli liczba referencji osiagnie 0 to 
	 * zasob jest zwalniany z pamieci.
	 */
	void release() { if(0 == (--refCount)) delete this; }


	/**
	 * Nazwa zasobu
	 */
	const std::string& getName() const { return name; }
	std::string& getName() { return name; }

	/**
	 * Typ zasobu
	 */
	virtual Type getType() const = 0;

	/**
	 * Bufor danych zasobu
	 */
	const void* getData() const { return data; }
	void* getData() { return data; }

	/**
	 * Rozmiar bufora danych zasobu
	 */
	unsigned getDataSize() const { return dataSize; }

};
